home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / lisp / stk-3.002 / stk-3 / STk-3.1 / Src / read.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-17  |  6.2 KB  |  260 lines

  1. /*
  2.  * r e a d  . c                -- reading stuff
  3.  *
  4.  * Copyright ⌐ 1993-1996 Erick Gallesio - I3S-CNRS/ESSI <eg@unice.fr>
  5.  * 
  6.  *
  7.  * Permission to use, copy, and/or distribute this software and its
  8.  * documentation for any purpose and without fee is hereby granted, provided
  9.  * that both the above copyright notice and this permission notice appear in
  10.  * all copies and derived works.  Fees for distribution or use of this
  11.  * software or derived works may only be charged with express written
  12.  * permission of the copyright holder.  
  13.  * This software is provided ``as is'' without express or implied warranty.
  14.  *
  15.  * This software is a derivative work of other copyrighted softwares; the
  16.  * copyright notices of these softwares are placed in the file COPYRIGHTS
  17.  *
  18.  *           Author: Erick Gallesio [eg@unice.fr]
  19.  *    Creation date: ??-Oct-1993 ??:?? 
  20.  * Last file update: 17-May-1996 18:39
  21.  *
  22.  */
  23.  
  24. #include <ctype.h>
  25. #include "stk.h"
  26.  
  27. static SCM lreadr(FILE *f, int case_significant);
  28.  
  29.  
  30. static int flush_ws(FILE *f, char *message)
  31. {
  32.   int c, commentp=0;
  33.  
  34.   c = Getc(f);
  35.   for ( ; ; ) {
  36.     switch (c) {
  37.       case EOF:  if (message) Err(message,NIL); else return(c);
  38.       case ';':  do 
  39.            c = Getc(f); 
  40.          while (c != '\n' && c != EOF);
  41.          continue;
  42.       case '\n': STk_line_counter += 1; break;
  43.       default:   if (!isspace(c)) return(c);
  44.     }
  45.     c = Getc(f);
  46.   }
  47. }
  48.  
  49. static SCM lreadlist(FILE *f, char delim, int case_significant)
  50. /* Read a list ended by the `delim' char */
  51. {
  52.   int c;
  53.   SCM tmp;
  54.   
  55.   c = flush_ws(f, "end of file inside list");
  56.   if (c == delim) return(NIL);
  57.  
  58.   /* Read the car */
  59.   Ungetc(c, f);
  60.   tmp = lreadr(f, case_significant);
  61.   
  62.   /* Read the cdr */
  63.   if (EQ(tmp, Sym_dot)) {
  64.     tmp = lreadr(f, case_significant);
  65.     c = flush_ws(f, "end of file inside list");
  66.     if (c != delim) Err("missing close paren", NIL);
  67.     return(tmp);
  68.   }
  69.   return(Cons(tmp, lreadlist(f, delim, case_significant)));
  70. }
  71.  
  72. static void lreadword(FILE *f, int c, int case_significant) 
  73. /* read an item whose 1st char is in c */
  74.   register int j = 0;
  75.   int allchars   = 0;
  76.  
  77.   for( ; ; ) {
  78.     allchars  ^= (c == '|');
  79.     if (c != '|') 
  80.       STk_tkbuffer[j++]  = (allchars || case_significant) ? c : tolower(c);
  81.  
  82.     c = Getc(f);
  83.     if (c == EOF) break;
  84.     if (!allchars) {
  85.       if (strchr("()[]'`,;\"\n", c)) {
  86.     Ungetc(c, f);
  87.     break;
  88.       }
  89.       if (isspace(c)) break;
  90.     }
  91.     if (j >= TKBUFFERN-1) Err("read: token too large", NIL);
  92.   }
  93.  
  94.   STk_tkbuffer[j] = '\0';
  95. }
  96.  
  97. static void lreadchar(FILE *f, int c)
  98. /* read an char (or a char name) item whose 1st char is in c */
  99.   register int j = 0;
  100.  
  101.   for( ; ; ) {
  102.     STk_tkbuffer[j++] = c;
  103.     c = Getc(f);
  104.     if (c == EOF || isspace(c)) break;
  105.     if (strchr("()[]'`,;\"", c)) {
  106.       Ungetc(c, f);
  107.       break;
  108.     }
  109.     if (j >= TKBUFFERN-1) Err("read: token too large", NIL);
  110.   }
  111.   STk_tkbuffer[j] = '\0';
  112. }
  113.   
  114. static SCM lreadtoken(FILE *f, int c, int case_significant) 
  115. {
  116.   SCM z;
  117.  
  118.   lreadword(f, c, case_significant);
  119.   z = STk_Cstr2number(STk_tkbuffer, 10L);
  120.  
  121.   if (z == Ntruth)
  122.     /* It is not a number */
  123.     return (*STk_tkbuffer == ':') ? STk_makekey(STk_tkbuffer): Intern(STk_tkbuffer);
  124.  
  125.   /* Return the number read */
  126.   return z;
  127. }
  128.  
  129. static SCM lreadstring(FILE *f)
  130. {
  131.   int j, k ,c,n,len;
  132.   char *p, *buffer;
  133.   SCM z;
  134.  
  135.   j = 0;
  136.   len = 100;
  137.   p = buffer = must_malloc(len);
  138.  
  139.   while(((c = Getc(f)) != '"') && (c != EOF)) { 
  140.     if (c == '\\') {
  141.       c = Getc(f);
  142.       if (c == EOF) Err("eof after \\", NIL);
  143.       switch(c) {
  144.         case 'b' : c = '\b'; break;    /* Bs  */
  145.     case 'e' : c = 0x1b; break;    /* Esc */
  146.     case 'n' : c = '\n'; break;    /* Lf  */
  147.     case 'r' : c = '\r'; break;    /* Cr  */
  148.     case 't' : c = '\t'; break;    /* Tab */
  149.         case '\n': STk_line_counter += 1; continue;
  150.     case '0' : for( k=n=0 ; ; k++ ) {
  151.              c = Getc(f);
  152.              if (c == EOF) Err("eof after \\0", NIL);
  153.                  if (isdigit(c) && (c < '8') && k < 3) /* Max = 3 digits */
  154.                 n = n * 8 + c - '0';
  155.              else {
  156.                Ungetc(c, f);
  157.                break;
  158.              }
  159.            }
  160.                c = n & 0xff;
  161.       }
  162.     }
  163.     else
  164.       if (c == '\n') STk_line_counter += 1;
  165.  
  166.     if ((j + 1) >= len) {
  167.       len = len + len / 2;
  168.       buffer = must_realloc(buffer, len);
  169.       p = buffer + j;
  170.     }
  171.     j++;
  172.     *p++ = c;
  173.   }
  174.   if (c == EOF) Err("end of file while reading a string", NIL);
  175.   *p = '\0';
  176.   
  177.   z = STk_makestrg(j, buffer);
  178.   free(buffer);
  179.  
  180.   return z;
  181. }
  182.  
  183. static SCM lreadr(FILE *f, int case_significant)
  184. {
  185.   int c;
  186.  
  187.   for ( ; ; ) {
  188.     c = flush_ws(f, "end of file inside read encountered");
  189.     
  190.     switch (c) {
  191.       case '(':
  192.         return(lreadlist(f, ')', case_significant));
  193.       case '[':
  194.     return(lreadlist(f, ']', case_significant));
  195.       case ')':
  196.       case ']':
  197.     fprintf(STk_stderr, "\nunexpected close parenthesis");
  198.     if (STk_current_filename != UNBOUND)    
  199.       fprintf(STk_stderr, " at line %d in file %s", 
  200.                     STk_line_counter, CHARS(STk_current_filename));
  201.     fprintf(STk_stderr, "\n");
  202.     break;
  203.       case '\'':
  204.     return LIST2(Sym_quote, lreadr(f, case_significant));
  205.       case '`':
  206.     return LIST2(Sym_quasiquote, lreadr(f, case_significant));
  207.       case '#':
  208.     switch(c=Getc(f)) {
  209.       case 't':
  210.           case 'T':  return Truth;
  211.       case 'f':
  212.       case 'F':  return Ntruth;
  213.        case '\\': lreadchar(f, Getc(f));
  214.                  return STk_makechar(STk_string2char(STk_tkbuffer));
  215.       case '(' : { 
  216.                    SCM l = lreadlist(f, ')', case_significant);
  217.                return STk_vector(l, STk_llength(l));
  218.                }
  219.       case '!' : while ((c=Getc(f)) != '\n')
  220.                    if (c == EOF) Err("eof encountered in a #! notation", NIL);
  221.              Ungetc(c, f);
  222.                  continue;
  223.       case 'p':
  224.       case 'P': lreadword(f, Getc(f), TRUE);
  225.                 return STk_address2object(STk_tkbuffer);
  226.       case '.': return STk_eval(lreadr(f, case_significant), NIL);
  227.       default:  Ungetc(c, f); return lreadtoken(f, '#', FALSE);
  228.     }
  229.       case ',': {
  230.     SCM symb;
  231.  
  232.     c = Getc(f);
  233.     if (c == '@') 
  234.       symb = Sym_unq_splicing;
  235.     else {
  236.       symb = Sym_unquote; 
  237.       Ungetc(c, f);
  238.     }
  239.     return LIST2(symb, lreadr(f, case_significant));
  240.       }
  241.       case '"':
  242.     return lreadstring(f);
  243.       default:
  244.     return lreadtoken(f, c, case_significant);
  245.     }
  246.   }
  247. }
  248.  
  249. SCM STk_readf(FILE *f, int case_significant)
  250. {
  251.   int c;
  252.   
  253.   c = flush_ws(f, (char *) NULL);
  254.   if (c == EOF) return(STk_eof_object);
  255.   Ungetc(c, f);
  256.   return lreadr(f, case_significant);
  257. }
  258.